package blazingbubble.legacy;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.File;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;

import spark.graphics.*;
import spark.math.Vector3;
import spark.math.Random;
import spark.utility.Clock;
import spark.exception.LoadingException;
import blazingbubble.legacy.game.Cannon;
import blazingbubble.legacy.game.BubbleField;
import blazingbubble.legacy.game.Bubble;
import blazingbubble.legacy.game.graphics.CannonRenderer;
import blazingbubble.legacy.game.graphics.BubbleRenderer;
import blazingbubble.legacy.game.graphics.BubbleFieldRenderer;
import blazingbubble.graphics.game.StaticSpriteMap;
import spark.graphics.ISpriteMap;
import com.sun.opengl.util.texture.TextureCoords;
import moltencore.game.bubble.Type;

public class Scene implements GLEventListener, KeyListener, MouseMotionListener
{
	private Camera camera = new Camera();
	private float cameraSpeed = 10.0f;
	private float oldX = 0;
	private float oldY = 0;
	private boolean w = false;
	private boolean a = false;
	private boolean s = false;
	private boolean d = false;
	private boolean left = false;
	private boolean right = false;
	private float passedMS = 0;

	private Cannon cannon;
	private int width = 8;
	private int height = 12;
	private Vector3 cannonPosition = new Vector3(width/2f, 0, -10);
	private CannonRenderer cannonRenderer;
	private BubbleRenderer bubbleRenderer;
	private BubbleField bubbleField;
	private Vector3 bubbleFieldLeftBottom;
	private BubbleFieldRenderer bubbleFieldRenderer;

	private Sprite lion;

	private Bubble nextBubble;

	public Scene()
	{
	}

	public void display(GLAutoDrawable drawable)
	{
		Clock.getInstance().update();
		doFrame();
	}

	private void doFrame()
	{
		passedMS += Clock.getInstance().getElapsedMilliseconds();
		if(passedMS > 1000)
		{
			//System.out.println("FPS " + Clock.getInstance().getFramesPerSecond());
			passedMS = 0;
		}
		if(s)
			camera.jump(-cameraSpeed * Clock.getInstance().getElapsedSeconds());
		if(w)
			camera.jump(cameraSpeed * Clock.getInstance().getElapsedSeconds());
		if(d)
			camera.strafe(-cameraSpeed * Clock.getInstance().getElapsedSeconds());
		if(a)
			camera.strafe(cameraSpeed * Clock.getInstance().getElapsedSeconds());
		if(left)
			cannon.move(Cannon.Direction.Left);
		if(right)
		{
			cannon.move(Cannon.Direction.Right);
		}

		Renderer.getInstance().getGl().glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		Renderer.getInstance().getGl().glLoadIdentity();

		camera.update();

		bubbleField.update();
		bubbleFieldRenderer.render(bubbleField, bubbleFieldLeftBottom);
		cannonRenderer.render(cannon, cannonPosition);
		bubbleRenderer.render(nextBubble, bubbleFieldLeftBottom);
		renderLion();
	}

	private void renderLion() {
		Renderer.getInstance().getGl().glPushMatrix();
		Renderer.getInstance().getGl().glTranslatef(10.0f, 10.0f, -10.0f);

		Texture currentTexture = lion.getTexture();

		currentTexture.bind();
		TextureCoords coords = currentTexture.getImageTexCoords();

		Renderer.getInstance().getGl().glBegin(GL.GL_QUADS);

		float r = Bubble.getRadius();
		float left = lion.getUvCoordinates().x;
		float right = lion.getUvCoordinates().x + lion.getDimensions().x;
		float top = lion.getUvCoordinates().y;
		float bottom = lion.getUvCoordinates().y + lion.getDimensions().y;

		Renderer.getInstance().getGl().glTexCoord2f(left, bottom);
		Renderer.getInstance().getGl().glVertex3f(-r, -r, 0);

		Renderer.getInstance().getGl().glTexCoord2f(right, bottom);
		Renderer.getInstance().getGl().glVertex3f(r, -r, 0);

		Renderer.getInstance().getGl().glTexCoord2f(right, top);
		Renderer.getInstance().getGl().glVertex3f(r, r, 0);

		Renderer.getInstance().getGl().glTexCoord2f(left, top);
		Renderer.getInstance().getGl().glVertex3f(-r, r, 0);

		Renderer.getInstance().getGl().glEnd();

		Renderer.getInstance().getGl().glPopMatrix();
	}

	public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged)
	{
	}

	public void init(GLAutoDrawable drawable)
	{
		Renderer.getInstance().initialize(drawable);
		Renderer.getInstance().setVSync(false);

		Renderer.getInstance().getGl().glEnable(GL.GL_TEXTURE_2D);
		Renderer.getInstance().getGl().glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
		Renderer.getInstance().getGl().glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);

		Renderer.getInstance().getGl().glEnable(GL.GL_BLEND);
		Renderer.getInstance().getGl().glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);

		ISpriteMap spriteMap = null;
		try {
			spriteMap = new StaticSpriteMap(Texture.newTexture(new File("resources/graphics/textures/bubbles_frozen_bubble.png"), true));
			lion = spriteMap.getSprite("stone");
		}
		catch(LoadingException e) {
			e.printStackTrace(); //TODO : auto generated stub
		}


		bubbleField = new BubbleField(width, height);
		bubbleFieldLeftBottom = new Vector3(0, 0, -10);
		bubbleFieldRenderer = new BubbleFieldRenderer();
		try
		{
			bubbleFieldRenderer.initializeWithTestLooks();
		}
		catch (LoadingException e)
		{
			e.printStackTrace();
		}
		cannon = new Cannon(1);
		cannonRenderer = new CannonRenderer();
		try
		{
			cannonRenderer.initializeWithTestLooks();
		}
		catch (LoadingException e)
		{
			e.printStackTrace();
		}
		bubbleRenderer = new BubbleRenderer();
		try
		{
			bubbleRenderer.initializeWithTestLooks();
		}
		catch (LoadingException e)
		{
			e.printStackTrace();
		}
		nextBubble = getRandomBubble();

		camera.strafe(-4);
		camera.jump(5);
		camera.walk(-15);

		for(int i = 2; i < bubbleField.getWidthInBubbles() - 1; i++)
		{
			for(float j = bubbleField.getHeight(); j > 7; j--)
			{
				Bubble bubble;
				int type = Random.getInstance().nextInt(6);
				type = 3;
				if(type == 0)
					bubble = new Bubble(new Vector3(i, j, 0), null, Bubble.Type.Rainbow);
				else if(type == 1)
					bubble = new Bubble(new Vector3(i, j, 0), null, Bubble.Type.Blazing);
				else if(type == 2)
					bubble = new Bubble(new Vector3(i, j, 0), null, Bubble.Type.Ghost);
				else
					bubble = new Bubble(new Vector3(i, j, 0), null, Bubble.Type.getRandomColoredType());
				bubbleField.positionBubble(bubble);
			}
		}
	}

	public void put(int x, int y)
	{
		y = height - y  + 1;
		Point currentPoint;
		float destinationX = 0;
		float destinationY = 0;
		currentPoint = new Point(x,y);
		destinationX = currentPoint.x;
		if(currentPoint.y % 2 == 0)
			destinationX += 0.5f;
		destinationY = ((float)currentPoint.y - 1.0f) * 0.875f;
		Bubble bubble = null;
		bubble = new Bubble(new Vector3(destinationX, destinationY, 0), null, Bubble.Type.Red);
		bubbleField.positionBubble(bubble);
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
	{
		Renderer.getInstance().resizeScenePerspectiveFov();
		//Renderer.getInstance().resizeSceneOrtho();
	}

	public void shutdown()
	{
	}

	public void keyPressed(KeyEvent event)
	{
		if(event.getKeyCode() == KeyEvent.VK_S)
		{
			s = true;
		}
		if(event.getKeyCode() == KeyEvent.VK_W)
		{
			w = true;
		}
		if(event.getKeyCode() == KeyEvent.VK_A)
		{
			a = true;
		}
		if(event.getKeyCode() == KeyEvent.VK_D)
		{
			d = true;
		}
		if(event.getKeyCode() == KeyEvent.VK_LEFT)
		{
			left = true;
		}
		if(event.getKeyCode() == KeyEvent.VK_RIGHT)
		{
			right = true;
		}
		if(event.getKeyCode() == KeyEvent.VK_UP)
		{
			Vector3 direction = cannon.getShootingDirection();
			direction.multiply(15);
			nextBubble.setVelocity(direction);
			bubbleField.spawnMovingBubble(nextBubble);
			nextBubble = getRandomBubble();
		}
	}

	public Bubble getRandomBubble()
	{
		Vector3 position = new Vector3(cannonPosition);
		position.z = 1;
		Bubble bubble = null;
		int type = 3;//Random.getInstance().getRandom().nextInt(6);
		if(type == 0)
			bubble = new Bubble(position, null, Bubble.Type.Rainbow);
		else if(type == 1)
			bubble = new Bubble(position, null, Bubble.Type.Blazing);
		else if(type == 2)
			bubble = new Bubble(position, null, Bubble.Type.Ghost);
		else
			bubble = new Bubble(position, null, Bubble.Type.getRandomColoredType());

		bubble.getPosition().z = 0.1f;
		return bubble;
	}

	public void keyReleased(KeyEvent event)
	{
		if(event.getKeyCode() == KeyEvent.VK_S)
		{
			s = false;
		}
		if(event.getKeyCode() == KeyEvent.VK_W)
		{
			w = false;
		}
		if(event.getKeyCode() == KeyEvent.VK_A)
		{
			a = false;
		}
		if(event.getKeyCode() == KeyEvent.VK_D)
		{
			d = false;
		}
		if(event.getKeyCode() == KeyEvent.VK_LEFT)
		{
			left = false;
		}
		if(event.getKeyCode() == KeyEvent.VK_RIGHT)
		{
			right = false;
		}
	}

	public void keyTyped(KeyEvent event)
	{
	}

	public void mouseDragged(MouseEvent arg0)
	{
	}

	public void mouseMoved(MouseEvent event)
	{
		float deltaX = event.getX() - oldX;
		oldX = event.getX();
		float deltaY = event.getY() - oldY;
		oldY = event.getY();
		//camera.setYaw(camera.getYaw() - deltaX * 0.33f);
		//camera.setPitch(camera.getPitch() + deltaY * 0.33f);
	}
}
